package dolf.game;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.util.*;
import dolf.objects.*;

/* singleton */

public class Level implements java.io.Serializable {
	private static final long serialVersionUID = 1L;
	
	private static Level instance = new Level();
	private Player aktPlayer = null; // this is the active player
	private List<WorldObject> objects = new LinkedList<WorldObject>(); // a list of all objects in the level
	private List<GroundObject> grounds = new LinkedList<GroundObject>(); // all ground objects
	private List<Hole> holes = new LinkedList<Hole>(); // all ground objects
	private List<Player> players = new LinkedList<Player>(); // a list of all players
	private List<WorldObject> animations = new LinkedList<WorldObject>(); //List for animations and BloodObjects
	private List<BloodObject> blood = new LinkedList<BloodObject>();
	private Point startpos; //the start position 
	private Point endpos; // position of the hole
	private boolean pressed; // true if mouse is pressed
	private boolean clicked; // true if mouse is clicked
	private int aktindex = 0; // index of aktPlayer
	private int phase = 0; // the phase of the game 
	private int xMouse; // x position of the mouse
	private int yMouse;	// y position of the mouse
	private int limit; // max kick offs
	private int width, height;
	private Loadbar loadbar = new Loadbar(new Point(100,100), 50, 8, Color.black, Color.green); // the kickoff bar
	private String background = null;
	private  transient Image bg; // background
	private Level(){
		phase = 3;
		objects.add(loadbar);
		loadbar.setVisible(false);
	}

	public static Level getInstance() {
		return instance;
	}

	public static void setInstance(Level l) {
		instance = l;
	}

	public Loadbar getLoadbar() {
		return loadbar;
	}
		
	public void flushLevel() {
		/*
		 * aktPlayer = null; objects.clear(); players.clear(); aktindex = 0;
		 * phase = 0; instance = new Level(); this.pressed = false; this.clicked =
		 * false;
		 */
		BloodManager.getInstance().flush();
		instance = new Level();
	}

	public List<WorldObject> getObjects() {
		return objects;
	}
	public List<GroundObject> getGrounds(){
		return this.grounds;
	}
	public List<Hole> getHoles(){
		return this.holes;
	}
	public List<WorldObject> getAnimations(){
		return this.animations;
	}
	public List<BloodObject> getBlood(){
		return this.blood;
	}
	public void registerObject(WorldObject obj){
		objects.add(0, obj);
	}

	public void registerObjectOnTop(WorldObject obj) {
		objects.add(obj);
	}
	public void registerGround(GroundObject obj){
		this.grounds.add(obj);
	}
	public void registerHole(Hole h){
		this.holes.add(h);
	}
	public void registerAnimation(WorldObject ani){
		this.animations.add(ani);
	}
	public void registerBlood(BloodObject bl){
		this.blood.add(bl);
	}

	public int getWidth(){
		return width;
	}
	
	public int getHeight(){
		return height;
	}
	public Point getMouse(){
		return new Point(xMouse,yMouse);
	}

	public void setMouse(int x, int y) {
		this.xMouse = x;
		this.yMouse = y;
	}

	public int getXMouse() {
		return this.xMouse;
	}

	public int getYMouse() {
		return this.yMouse;
	}

	public boolean mousePressed() {
		return this.pressed;
	}

	public void setPressed(boolean val) {
		this.pressed = val;
	}

	public boolean mouseClicked() {
		return this.clicked;
	}

	public void setClicke(boolean val) {
		this.clicked = val;
	}
	public void removeObject(WorldObject obj) {
		objects.remove(obj);
	}
	
	public void removeGround(GroundObject obj){
		objects.remove(obj);
	}
	public boolean removeAnimation(WorldObject ani){
		return this.animations.remove(ani);
	}
	public boolean removeBlood(BloodObject bl){
		return blood.remove(bl);
	}
	public void removeAllBlood(){
		this.blood = new LinkedList<BloodObject>();
	}
	
	public Point getStartPos(){
		return startpos;		
	}
	
	public Point getEndPos() {
		return endpos;
	}

	public List<Player> getPlayers() {
		return this.players;
	}

	public void registerPlayer(Player player) {
		this.players.add(player);
	}

	public void removePlayer(Player pl) {
		this.objects.remove(pl.getBall());
		if (pl == this.aktPlayer) {
			this.aktindex = this.players.indexOf(pl);
			this.aktPlayer = null;
		}
		this.players.remove(pl);
		if(pl.getAktWeapon() != null){
			pl.getAktWeapon().remove();
		}
	}

	public Player getAktualPlayer() {
		return aktPlayer;
	}

	public void setAktualPlayer(Player player) {
		this.aktPlayer = player;
	}

	public Player getNextPlayer() {
		if (this.players.isEmpty()) {
			System.out.println("leer");
			return null;
		}
		if (this.aktPlayer == null) {
			return this.aktPlayer = this.players.get(this.aktindex
					% this.players.size());
		}
		if (players.indexOf(aktPlayer) == -1) {
			return this.aktPlayer = this.players.get(this.aktindex
					% this.players.size());
		}
		return this.aktPlayer = this.players.get((this.players
				.indexOf(this.aktPlayer) + 1)
				% this.players.size());
	}

	public int getPhase() {
		return this.phase;
	}

	public void setPhase(int _phase) {
		this.phase = _phase;
	}
	
	public int getLimit(){
		return this.limit;
	}
	
	public boolean noMotion() {
		if(!this.animations.isEmpty() || !this.blood.isEmpty()){
			return false;
		}
		for (WorldObject wo : this.objects) {
			if (wo instanceof CircleObject) {
				if (wo.isVisible() && wo.isMoving()) {
					return false;
				}
			}
		}
		return true;
	}

	public boolean noBallMotion() {
		for (Player pl : this.players) {
			if (pl.getBall().isMoving()) {
				return false;
			}
		}
		return true;
	}
	public boolean animationRunning(){
		return !this.animations.isEmpty();
	}
	public boolean bloodFlow(){
		return !this.blood.isEmpty();
	}
	public void loadParcours(Parcours p) {
		this.grounds.addAll(p.getGrounds());
		this.objects.addAll(p.getObjects());
		this.holes.addAll(p.getHoles());
		this.startpos = p.getStartPos();
		this.width = p.getWidth();
		this.height = p.getHeight();
		this.background = p.getBackground();
		Image back = ImageStore.getInstance().getImage(background);
		this.bg = back.getScaledInstance(width, height, Image.SCALE_FAST);
		this.limit = p.getLimit();
		Player.incAktPacour();
	}
	
	public void paint(Graphics2D g){
		if( bg== null){
			Image back = ImageStore.getInstance().getImage(background);
			this.bg = back.getScaledInstance(width, height, Image.SCALE_FAST);
		}
		g.drawImage(this.bg, 0, 0, null);
	}
	
}
